﻿/**
 *     XCLIKEE
 */
namespace PropertyBinding
{
    using System;

    public class PropertyBinding 
    {
        /// <summary>
        /// 属性名称
        /// </summary>
        public string PropertyName { get; private set; }

        /// <summary>
        /// 属性更改事件
        /// </summary>
        private Action<object> OnChangeEvent;

        /// <summary>
        /// 获得属性值
        /// </summary>
        private Func<object> OnGetValue;

        public PropertyBinding(string bindName, Func<object> onGetValue) : this(bindName, onGetValue, true)
        {

        }
        public PropertyBinding(string bindName, Func<object> onGetValue, bool addBinding = true)
        {
            PropertyName = bindName;
            OnGetValue = onGetValue;
            OnChangeEvent = null;

            if (addBinding)
                PropertyBindingMa.AddBinding(this);
        }

        public virtual void AddListener(Action<object> onChangeEvent)
        {
            this.OnChangeEvent += onChangeEvent;
            onChangeEvent?.Invoke(GetValue());
        }

        public virtual void RemoveListener(Action<object> onChangeEvent)
        {
            if (null != this.OnChangeEvent)
                this.OnChangeEvent -= onChangeEvent;
        }

        /// <summary>
        /// 获得属性值
        /// </summary>
        /// <returns></returns>
        public virtual object GetValue()
        {
            if (null == OnGetValue)
                return default(object);

            return OnGetValue();
        }

        /// <summary>
        /// 通知属性更改
        /// </summary>
        public virtual void NotfiyValueChange()
        {
            this.OnChangeEvent?.Invoke(GetValue());
        }
    }

    public class PropertyBindingType<T> : PropertyBinding
    {
        public delegate void PropertyChangeDelegate(T value);

        /// <summary>
        /// 属性更改事件
        /// </summary>
        private PropertyChangeDelegate OnChangeEvent;
        /// <summary>
        /// 获得属性值
        /// </summary>
        private Func<object, T> OnGetValue;

        private object Data;

        public PropertyBindingType(string bindName, Func<object, T> onGetValue, object data = null) : base(bindName, null, false)
        {
            OnGetValue = onGetValue;
            Data = data;
            PropertyBindingMa.AddBinding(this);
        }

        /// <summary>
        /// 注册通知消息
        /// 
        /// 注册时会主动通知一次
        /// </summary>
        /// <param name="onChangeEvent"></param>
        public void AddListenerT(PropertyChangeDelegate onChangeEvent)
        {
            this.OnChangeEvent += onChangeEvent;
            onChangeEvent?.Invoke(GetValueT());
        }

        public void RemoveListenerT(PropertyChangeDelegate onChangeEvent)
        {
            if (null != this.OnChangeEvent)
                this.OnChangeEvent -= onChangeEvent;
        }

        public override object GetValue()
        {
            return GetValueT();
        }
        public T GetValueT()
        {
            if (null == OnGetValue)
                return default(T);

            return OnGetValue(Data);
        }

        /// <summary>
        /// 通知属性更改
        /// </summary>
        public override void NotfiyValueChange()
        {
            this.OnChangeEvent?.Invoke(GetValueT());
        }

        /// <summary>
        /// 注册通知消息
        /// 
        /// 注册时会主动通知一次
        /// </summary>
        /// <param name="name"></param>
        /// <param name="onChangeEvent"></param>
        public static void AddListenerT(string name, PropertyChangeDelegate onChangeEvent)
        {
            var property = PropertyBindingMa.GetBinding<T>(name);
            if (property == null)
            {
                throw new Exception($"{name}  属性不存在");
            }
            else
            {
                property.AddListenerT(onChangeEvent);
            }
        }
    }

}
